import Foundation
import Combine

class HomeViewModel: ObservableObject {
    @Published var waterIntakeStore = WaterIntakeStore()
    @Published var userProfile = UserProfile()
    @Published var todayTotal: Double = 0
    @Published var progress: Double = 0
    @Published var streakDays: Int = 0
    @Published var achievementPoints: Int = 0
    
    // 健康提示列表
    private let healthTips = [
        "每天早上起床后喝一杯水，可以补充夜间流失的水分",
        "定期饮水有助于提高认知功能和体力",
        "保持良好的饮水习惯可以改善皮肤状况",
        "喝水前先喝一口，让口腔适应，能够更好地感受水的味道",
        "适量饮水可以帮助减轻体重和控制食欲",
        "运动前后半小时内补充足够的水分很重要",
        "温水比冷水更容易被身体吸收",
        "不要等到口渴时才喝水，口渴是身体缺水的信号",
        "每天喝8杯水是保持健康的基本要求",
        "饮水过多也会对健康不利，每小时最好不要超过1升水"
    ]
    
    // 成就列表
    private let achievements = [
        "初学者": "首次记录饮水量",
        "坚持不懈": "连续7天达到饮水目标",
        "水润达人": "连续30天达到饮水目标",
        "精准把控": "3天内饮水量与目标值相差不超过100ml",
        "清晨活力": "连续5天在早晨8点前记录第一杯水",
        "健康常伴": "使用应用满30天"
    ]
    
    private var cancellables = Set<AnyCancellable>()
    
    init() {
        // 监听今日饮水总量变化
        waterIntakeStore.$intakes
            .map { _ in self.waterIntakeStore.getTodayTotal() }
            .assign(to: \.todayTotal, on: self)
            .store(in: &cancellables)
        
        // 监听进度变化
        Publishers.CombineLatest($todayTotal, userProfile.$goal)
            .map { total, goal in
                min(total / goal, 1.0) // 确保进度不超过100%
            }
            .assign(to: \.progress, on: self)
            .store(in: &cancellables)
        
        // 计算连续达标天数
        calculateStreakDays()
        
        // 计算成就点数
        calculateAchievementPoints()
    }
    
    // 记录喝水
    func recordWaterIntake(amount: Double) {
        waterIntakeStore.addIntake(amount: amount, goal: userProfile.goal)
        checkForNewAchievements()
    }
    
    // 获取距离目标的剩余量
    func getRemainingAmount() -> Double {
        return max(userProfile.goal - todayTotal, 0)
    }
    
    // 检查是否已达到目标
    func hasReachedGoal() -> Bool {
        return todayTotal >= userProfile.goal
    }
    
    // 获取随机健康提示
    func getDailyHealthTip() -> String {
        let day = Calendar.current.ordinality(of: .day, in: .year, for: Date()) ?? 0
        let index = day % healthTips.count
        return healthTips[index]
    }
    
    // 获取今日饮水记录
    func getTodayRecords() -> [WaterIntake] {
        let calendar = Calendar.current
        let today = calendar.startOfDay(for: Date())
        
        return waterIntakeStore.intakes
            .filter { calendar.isDate($0.date, inSameDayAs: today) }
            .sorted { $0.date > $1.date }
    }
    
    // 计算连续达标天数
    private func calculateStreakDays() {
        let calendar = Calendar.current
        let today = calendar.startOfDay(for: Date())
        
        var currentStreak = 0
        var currentDate = today
        
        // 按天分组饮水记录
        let groupedByDay = Dictionary(grouping: waterIntakeStore.intakes) { intake in
            calendar.startOfDay(for: intake.date)
        }
        
        // 计算连续达标天数
        while true {
            let dayRecords = groupedByDay[currentDate] ?? []
            let dayTotal = dayRecords.reduce(0) { $0 + $1.amount }
            
            // 如果这一天没有记录或者没有达标，结束计算
            if dayRecords.isEmpty || dayTotal < userProfile.goal {
                break
            }
            
            currentStreak += 1
            
            // 移动到前一天
            guard let previousDay = calendar.date(byAdding: .day, value: -1, to: currentDate) else {
                break
            }
            currentDate = previousDay
            
            // 如果到了30天前，就不再继续查找
            if let thirtyDaysAgo = calendar.date(byAdding: .day, value: -30, to: today),
               currentDate < thirtyDaysAgo {
                break
            }
        }
        
        streakDays = currentStreak
    }
    
    // 检查是否获得新成就并计算成就点数
    private func checkForNewAchievements() {
        // 在这里可以实现成就检查和点数计算逻辑
        calculateAchievementPoints()
    }
    
    // 计算成就点数
    private func calculateAchievementPoints() {
        // 这是一个简单的成就点数计算示例
        var points = 0
        
        // 连续天数成就
        if streakDays >= 7 {
            points += 10
        }
        if streakDays >= 30 {
            points += 50
        }
        
        // 今日进度成就
        if progress >= 1.0 {
            points += 5
        }
        
        // 按照饮水记录数量计算
        let recordCount = waterIntakeStore.intakes.count
        points += min(recordCount, 100)
        
        achievementPoints = points
    }
} 